package com.demo.socket;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用JDK 21虚线程实现的Socket客户端
 */
public class VirtualThreadSocketClient {
    private static final String SERVER_HOST = "localhost";
    private static final int SERVER_PORT = 8080;
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

    public static void main(String[] args) {
        // 使用虚线程执行客户端逻辑
        try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
            executor.submit(VirtualThreadSocketClient::startClient);
            
            // 等待客户端任务完成
            executor.shutdown();
            while (!executor.isTerminated()) {
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 启动客户端并连接服务器
     */
    private static void startClient() {
        System.out.printf("[%s] 客户端启动，连接到服务器 %s:%d%n",
                LocalTime.now().format(TIME_FORMATTER),
                SERVER_HOST,
                SERVER_PORT);
        System.out.printf("客户端线程: %s (是否为虚线程: %b)%n",
                Thread.currentThread().getName(),
                Thread.currentThread().isVirtual());

        try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
             BufferedReader in = new BufferedReader(
                     new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
             PrintWriter out = new PrintWriter(
                     new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
             Scanner scanner = new Scanner(System.in)) {

            // 启动一个单独的虚线程来读取服务器响应
            Thread responseThread = Thread.startVirtualThread(() -> {
                try {
                    String response;
                    while ((response = in.readLine()) != null) {
                        System.out.printf("[%s] 服务器响应: %s%n",
                                LocalTime.now().format(TIME_FORMATTER),
                                response);
                    }
                } catch (IOException e) {
                    System.err.println("读取服务器响应出错: " + e.getMessage());
                }
            });

            // 主线程用于发送消息到服务器
            System.out.println("请输入消息发送到服务器（输入exit退出）:");
            String userInput;
            while (scanner.hasNextLine() && !(userInput = scanner.nextLine()).equalsIgnoreCase("exit")) {
                out.println(userInput);
            }

            // 发送退出命令
            out.println("exit");
            responseThread.join(1000); // 等待响应线程处理完最后的消息

        } catch (UnknownHostException e) {
            System.err.println("无法连接到服务器: " + SERVER_HOST);
        } catch (IOException e) {
            System.err.println("客户端I/O错误: " + e.getMessage());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        System.out.println("客户端已退出");
    }
}
